import WebpackLicense from '@components/WebpackLicense';

<WebpackLicense from="https://webpack.docschina.org/api/stats/" />

# Stats JSON

使用 Rspack 编译时，可通过如下命令生成统计模块信息的 JSON 文件，以分析应用的模块依赖关系：

```bash
# 生成名为 `compilation-stats.json` 的统计信息 JSON 文件
$ rspack --json=compilation-stats.json
```

## 整体结构

输出的对象的顶层结构如下：

```ts
type StatsCompilation = {
  // 固定的模拟 webpack 版本号，用于兼容社区 webpack 插件
  version?: string;
  // 当前 rspack 版本号
  rspackVersion?: string;
  // 配置中的 `name`
  name?: string;
  // 编译的哈希值
  hash?: string;
  // 编译耗时（毫秒）
  time?: number;
  // 编译结束时间戳
  builtAt?: number;
  // 配置中的 `output.publicPath`
  publicPath?: string;
  // 输出目录路径
  outputPath?: string;
  // chunk 对应的输出文件列表
  assetsByChunkName?: Record<string, string[]>;
  // asset 对象列表，详细结构参考《Asset 对象结构》章节
  assets?: StatsAsset[];
  // chunk 对象列表，详细结构参考《Chunk 对象结构》章节
  chunks?: StatsChunk[];
  // module 对象列表，详细结构参考《Module 对象结构》章节
  modules?: StatsModule[];
  // entry 对象，详细结构参考《Entry/ChunkGroup 对象结构》章节
  entrypoints?: Record<string, StatsChunkGroup>;
  // chunk group 对象，详细结构参考《Entry/ChunkGroup 对象结构》章节
  namedChunkGroups?: Record<string, StatsChunkGroup>;
  // error 对象列表，详细结构参考《Error/Warning 对象结构》章节
  errors?: StatsError[];
  // 错误个数
  errorsCount?: number;
  // warning 对象列表，详细结构参考《Error/Warning 对象结构》章节
  warnings?: StatsWarnings[];
  // 告警个数
  warningsCount?: number;
};
```

## Asset 对象结构

每个 asset 对象对应一个编译过程中生成的产物文件，它的结构如下：

```ts
type StatsAsset = {
  // 产物的文件名
  name: string;
  // 产物的文件大小（单位为字节）
  size: number;
  // 产物文件是否生成到 `output` 目录中
  emitted: boolean;
  // 产物文件关联的 chunk 的 ID 列表
  chunks: Array<string | undefined | null>;
  // 产物文件关联的 chunk 的名称列表
  chunkNames: Array<string>;
  // 产物文件关联的 chunk 的 idHint 列表
  chunkIdHInts: Array<string>;
  // 作为附属产物文件关联的 chunk 的 ID 列表
  auxiliaryChunks: Array<string | undefined | null>;
  // 作为附属产物文件关联的 chunk 的名称列表
  auxiliaryChunkNames: Array<string>;
  // 作为附属产物文件关联的 chunk 的 idHint 列表
  auxiliaryChunkIdHints: Array<string>;

  // 产物的信息
  info: {
    // 该产物是否经过代码压缩
    minimized: boolean;
    // 该产物是否仅用于 development 环境
    development: boolean;
    // 该产物是否仅用于 HMR 更新场景
    hotModuleReplacement: boolean;
    // 从源文件创建产物时（可能转换）sourceFilename
    // 常见于处理 assets 类型的资源和使用 CopyRspackPlugin 等场景
    sourceFilename?: string;
    // 该产物是否可被持久化缓存（包含哈希值）
    immutable: boolean;
    // 该产物是否为 ESM 文件
    javascriptModule?: boolean;
    // 产物的 chunk 哈希值
    chunkHash: Array<string>;
    // 产物的内容哈希值
    contentHash: Array<string>;
  };
  // 相关联的产物，如 source-map
  related: StatsAsset[];
  // 产物体积是否超过 performance.maxAssetSize 配置
  isOverSizeLimit?: boolean;
};
```

## Chunk 对象结构

每个 chunk 对象对应一个编译过程中产生的 chunk，它的结构如下：

```ts
type StatsChunk = {
  // chunk 包含的产物文件列表
  files: Array<string>;
  // chunk 包含的附属产物文件列表
  auxiliaryFiles: Array<string>;
  // chunk 的 ID
  id?: string;
  // chunk 包含的 chunk 的名称列表
  names: Array<string>;
  // chunk 所使用的 runtime
  runtime: Array<string>;
  // chunk 的大小（单位为字节）
  size: number;
  // chunk 根据模块类型细分的大小（单位为字节）
  sizes: Record<string, number>;
  // chunk 的哈希值
  hash?: string;
  // chunk 是否包含 runtime
  entry: boolean;
  // chunk 是否应被页面初始加载
  initial: boolean;
  // chunk 是否生成产物
  rendered: boolean;

  // 父级 chunk 的 ID 列表
  parents?: Array<string>;
  // 子 chunk 的 ID 列表
  children?: Array<string>;
  // 同级 chunk 的 ID 列表
  siblings?: Array<string>;

  // 生成 chunk 的原因（需开启 optimization.splitChunks）
  reason?: string;
  // split chunks 时命中的 cache group 的 idHint 列表（需开启 optimization.splitChunks）
  idHints: Array<string>;

  // chunk 的引入来源列表
  origins: Array<{
    // 来源 module 的路径
    module: string;
    // 来源 module 的 ID
    moduleId: string;
    // 来源 module 的唯一标识
    moduleIdentifier: string;
    // 来源 module 的相对路径
    moduleName: string;
    // 在来源 module 中的代码位置
    loc: string;
    // 在来源 module 中的依赖标识
    request: string;
  }>;

  // chunk 内包含的 module 列表，详细结构参考《Module 对象结构》章节
  modules?: Array<StatsModule>;
};
```

## Module 对象结构

每个 module 对象对应一个编译过程中产生的模块，它的结构如下：

```ts
type StatsModule = {
  // 模块的 ID
  id?: string;
  // 模块的类型
  moduleType: string;
  // 模块的唯一标识
  identifier: string;
  // 模块的相对路径
  name: string;
  // 模块的大小（单位为字节）
  size: number;
  // 根据模块类型细分的大小（单位为字节）
  sizes: Record<string, number>;

  // 模块是否经过编译阶段
  built: boolean;
  // 模块是否经过了代码生成阶段
  codeGenerated: boolean;
  // 模块是否在编译时运行（常见于 css-extract 等场景）
  buildTimeExecuted: boolean;
  // 模块是否被缓存
  cached: boolean;
  // 模块是否可被缓存
  cacheable: boolean;
  // 模块是否可选，若可选当模块未找到时仅会出现警告
  optional: boolean;
  // 模块是否被依赖
  dependent?: boolean;

  // 模块被引入的原因列表，与 chunk.origins 结构类似
  reasons?: Array<JsStatsModuleReason>;
  // 父模块的唯一标识
  issuer?: string;
  // 父模块的 ID
  issuerId?: string;
  // 父模块的相对路径
  issuerName?: string;
  // 从 entry 到当前模块的引用路径
  issuerPath: Array<JsStatsModuleIssuer>;
  // 模块用于条件匹配的绝对路径（通常是资源路径）
  nameForCondition?: string;
  // 模块在 Chunk Group 中自顶向下的序号
  preOrderIndex?: number;
  // 模块在 Chunk Group 中自底向上的序号
  postOrderIndex?: number;
  // 模块距离 entry 的层级距离
  depth?: number;
  // 模块是否未被任何 chunk 包含
  orphan: boolean;
  // 包含模块的 chunk 的 ID 列表
  chunks: Array<string | undefined | null>;
  // 模块相关的产物列表
  assets?: Array<string>;

  // 模块是否编译失败
  failed: boolean;
  // 模块包含的错误数量
  errors: number;
  // 模块包含的警告数量
  warnings: number;

  // 被使用的模块导出，true 表示全部被使用，string[] 表示部分字段被使用（需开启 optimization.usedExports 配置）
  usedExports?: null | string[] | boolean;
  // 模块导出的字段列表（需开启 optimization.providedExports 配置）
  providedExports?: null | string[];
  // 模块优化降级信息（需开启 optimization.concatenateModules 配置）
  optimizationBailout?: null | string[];

  // 若当前模块为作用域提升后生成的新模块，此字段为原始的模块列表（需开启 optimization.concatenateModules 配置）
  modules?: Array<JsStatsModule>;

  // 模块的源代码
  source?: string | Buffer;

  // 模块各阶段编译耗时统计（单位为毫秒，需开启 profile 配置）
  profile?: {
    // 查找模块
    resolving: number;
    // 编译模块
    building: number;
  };
};
```

## Entry/ChunkGroup 对象结构

每个 entry 对象对应一个编译入口，它的结构如下：

```ts
type StatsEntrypoints = Record<string, StatsChunkGroup>;
type StatsNamedChunkGroups = Record<string, StatsChunkGroup>;

type StatsChunkGroup = {
  // entry 的名称
  name: string;
  // 包含的 chunk 的 ID 列表
  chunks: Array<string | undefined | null>;
  // chunk group 的产物文件
  assets: Array<{
    // 产物文件名
    name: string;
    // 产物文件大小
    size: number;
  }>;
  // chunk group 总产物大小
  assetsSize: number;
  // chunk group 的附属产物文件，如 sourcemap
  auxiliaryAssets?: Array<{
    // 附属产物文件名
    name: string;
    // 附属产物文件大小
    size: number;
  }>;
  // chunk group 的总附属产物大小，如 sourcemap
  auxiliaryAssetsSize?: number;
  // 子 chunk group 加载顺序，按照优先级排序
  children?: {
    // 需 preload 的 子 chunk group
    preload?: Array<StatsChunkGroup>;
    // 需 prefetch 的 子 chunk group
    prefetch?: Array<StatsChunkGroup>;
  };
  // 子 chunk group 加载文件顺序，按照优先级排序
  children?: {
    // 需 preload 的资源文件
    preload?: Array<string>;
    // 需 prefetch 的资源文件
    prefetch?: Array<string>;
  };
  // 是否入口的产物体积超过了 performance.maxEntrypointSize
  isOverSizeLimit?: boolean;
};
```

## Error/Warning 对象结构

每个 error/warning 对象对应一个构建过程中产生的错误/警告，它的结构如下：

```ts
type StatsError = {
  // 错误/警告的可视化提示信息
  message: string;
  // 与此错误/警告关联的自定义文件名
  file?: string;
  // 错误/警告的明细信息
  details?: string;
  // 错误/警告的栈信息
  stack?: string;
  /**
   * 与此错误/警告相关的模块标识符
   * 通常是绝对路径，可能包含内联的 loader request
   * @example
   * - `/path/to/project/src/index.js`
   * - `!builtin:react-refresh-loader!/path/to/project/src/index.css`
   */
  moduleIdentifier?: string;
  /**
   * 与此错误/警告相关的模块可读名称
   * 通常是相对路径，不包含内联的 loader request
   * @example
   * - `"./src/index.js"`
   * - `"./src/index.css"`
   */
  moduleId?: string;
  // 错误/警告的模块引用路径
  moduleTrace: Array<JsStatsModuleTrace>;

  // 若在 chunk 生成时错误/警告，关联的 chunk 名称
  chunkName?: string;
  // 若在 chunk 生成时错误/警告，关联的 chunk 是否为 entry
  chunkEntry?: boolean;
  // 若在 chunk 生成时错误/警告，关联的 chunk 是否为 initial
  chunkInitial?: boolean;
  // 若在 chunk 生成时错误/警告，关联的 chunk 是否为 initial
  chunkId?: string;
};
```
